package com.eshopkeeper.core.util.yunzhi;


import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Request工具类
 * @author chen
 *
 */
public class RequestUtil {

    private static final Logger logger = LogManager.getLogger(RequestUtil.class);

    public static RequestHeader decodeHeader(HttpServletRequest request) {
        RequestHeader header = new RequestHeader();
        String token = request.getHeader("ifcToken");
        if (!StringUtil.isEmpty(token)) {
            JWT jwt = JWT.decode(token);
            header.setToken(token);
            header.setUserId(Long.valueOf(jwt.getSubject()));
            header.setIssueAt(jwt.getIssuedAt().getTime());
            header.setExpiresAt(jwt.getExpiresAt().getTime());
        }
        header.setAppName(request.getParameter("appName"));
        header.setAppVersion(request.getParameter("appVersion"));
        header.setOs(request.getParameter("os"));
        header.setOsVersion(request.getParameter("osVersion"));
        header.setBrand(request.getParameter("brand"));
        header.setModel(request.getParameter("model"));
        header.setUuid(request.getParameter("uuid"));
        header.setNetworkType(request.getParameter("networkType"));
        header.setResolution(request.getParameter("resolution"));
        header.setSt(StringUtil.isEmpty(request.getParameter("st"))
                ? 0L : Long.valueOf(request.getParameter("st")));
        header.setSign(request.getParameter("sign"));
        logger.info("RequestHeader-" + header.toString());
        return header;

    }
    public static RequestHeader decodeHeaderRun(HttpServletRequest request) {
        RequestHeader header = new RequestHeader();
        String token = request.getHeader("huiToken");
        if (!StringUtil.isEmpty(token)) {
            JWT jwt = JWT.decode(token);
            header.setToken(token);
            header.setUserId(Long.valueOf(jwt.getSubject()));
            header.setIssueAt(jwt.getIssuedAt().getTime());
            header.setExpiresAt(jwt.getExpiresAt().getTime());
        }
        header.setAppName(request.getParameter("appName"));
        header.setAppVersion(request.getParameter("appVersion"));
        header.setOs(request.getParameter("os"));
        header.setOsVersion(request.getParameter("osVersion"));
        header.setBrand(request.getParameter("brand"));
        header.setModel(request.getParameter("model"));
        header.setUuid(request.getParameter("uuid"));
        header.setNetworkType(request.getParameter("networkType"));
        header.setResolution(request.getParameter("resolution"));
        header.setSt(StringUtil.isEmpty(request.getParameter("st"))
                ? 0L : Long.valueOf(request.getParameter("st")));
        header.setSign(request.getParameter("sign"));
        logger.info("RequestHeader-" + header.toString());
        return header;

    }

    public static String decodeRequestData(HttpServletRequest request) throws Exception {
        String data = request.getParameter("data");
        if (StringUtil.isEmpty(data)){
            logger.info("请求时data参数为空");
            return null;
        }
        data = DES3Util.decode(data);
        data = java.net.URLDecoder.decode(data, "UTF-8");
        return data;
    }

    public static Map<String, Object> decodeData(HttpServletRequest request) throws Exception {
        String data = decodeRequestData(request);
        if(StringUtil.isEmpty(data))
            return null;
        logger.info("data-" + data);
        return JsonUtil.toMap(data);
    }

    public static JSONObject decodeDataJson(HttpServletRequest request) throws Exception {
        String data = decodeRequestData(request);
        if(StringUtil.isEmpty(data))
            return null;
        logger.info("data-" + data);
        return JSONObject.parseObject(data);
    }



    public static boolean validToken(HttpServletRequest request) {
        String token = request.getHeader("ifcToken");
        logger.info("ifcToken-" + token);
        return validToken(token);
    }
    public static boolean validTokenRun(HttpServletRequest request) {
        String token = request.getHeader("huiToken");
        logger.info("huiToken-" + token);
        return validToken(token);
    }

    private static boolean validToken(String token) {
        if (StringUtil.isEmpty(token))
            return false;
        DecodedJWT jwt;
        try {
            jwt = JWT.require(Algorithm.HMAC256(Config.TOKEN_HMAC256_KEY)).build().verify(token);
        } catch (Exception e) {
            logger.info("token验证失败", e);
            return false;
        }
        if (jwt.getSubject() == null) {
            logger.error("token验证失败，用户为空");
            return false;
        }
        return true;
    }

//    private static String join(Map<String, String> params) {
//        return StringUtil.join(toList(params.entrySet()), "&");
//    }

    private static Map<String, String> split(String params) {
        Map<String, String> map = new HashMap<>();
        if (StringUtil.isEmpty(params)) {
            return map;
        }
        if (!params.contains("&")) {
            split(params, map);
            return map;
        }
        String[] values = params.split("&");
        for (String value : values) {
            split(value, map);
        }
        return map;
    }

    private static String join(Map.Entry<String, String> entry) {
        return entry.getKey() + "=" + entry.getValue();
    }

    private static void split(String value, Map<String, String> params) {
        params.put(StringUtil.find(value, "[^=]+=", "[^=]+"), StringUtil.find(value, "=[^=]+", "[^=]+"));
    }

    private static List<String> toList(Set<Map.Entry<String, String>> entries) {
        List<String> list = new ArrayList<>();
        for (Map.Entry<String, String> entry : entries) {
            list.add(join(entry));
        }
        return list;
    }

    public static boolean validSign(HttpServletRequest request) {
        String signString = request.getQueryString();
        logger.info("sign-" + signString);
        return validSign(split(signString));
    }

    public static boolean validSign(Map<String, String> map) {
        String sign = map.get("sign");
        return genSign(map, Config.APP_SIGN_MD5_KEY).equals(sign);
    }

    /**
     * 生成签名
     *
     * @return 签名
     */
    public static String genSign(Map<String, String> map, String md5key) {
        List<String> keys = sortKeyList(map);//排序key
        String content = "key=" + md5key;//密钥排第一位
        for (String key : keys) {
            if ("sign".equals(key))
                continue;
            content += "&" + key + "="
                    + (null == map.get(key) ? "" : String.valueOf(map.get(key)));
        }
        return DigestUtils.md5Hex(content);
    }

    public static List<String> sortKeyList(Map<String, String> map) {
        List<String> list = new ArrayList<>(map.keySet());
        list.sort(String.CASE_INSENSITIVE_ORDER);//按字符排序，不区分大小写
        return list;
    }

    public static String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }
}
